package com.hetwen.search.demo.push;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;

import com.hetwen.search.demo.ISendMsg;

import org.apache.mina.core.filterchain.IoFilter;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class PushService extends Service {

    private static final String TAG = "PushService";

    private static final String IP = "192.168.31.239";

    private static final int PORT = 8088;

    private static final int KEEP_ALIVE_INTERVAL = 10;

    private static final int KEEP_ALIVE_TIMEOUT = 5;

    private boolean isRunning;

    private BlockingQueue<String> sendQueue;

    private PushBinder binder;

    public PushService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
        sendQueue = new ArrayBlockingQueue<>(100);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        if (binder == null) {
            binder = new PushBinder();
        }
        return binder;
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        if (!isRunning) {
            isRunning = true;
            PushThread t = new PushThread();
            t.start();
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
        isRunning = false;
    }

    private class PushThread extends Thread {

        public PushThread() {
        }

        @Override
        public void run() {
            SocketConnector connector = new NioSocketConnector();
            connector.setConnectTimeoutMillis(5000);
            IoFilter filter = new ProtocolCodecFilter(new TextLineCodecFactory());
            connector.getFilterChain().addLast("codec", filter);

            //心跳保活
            KeepAliveFilter heartBeat = new KeepAliveFilter(new KeepAliveMessageFactoryImpl(), IdleStatus.BOTH_IDLE);
            heartBeat.setForwardEvent(true);
            heartBeat.setRequestInterval(KEEP_ALIVE_INTERVAL);
            heartBeat.setRequestTimeout(KEEP_ALIVE_TIMEOUT);
            connector.getFilterChain().addLast("heartbeat", heartBeat);

            SocketAddress addr = new InetSocketAddress(IP, PORT);
            connector.setHandler(new ClientHandler(PushService.this));
            ConnectFuture future = connector.connect(addr);
            future.awaitUninterruptibly(5000);
            IoSession session = null;
            if (future.isConnected()) {
                Log.d(TAG, IP + ":" + PORT + " 连接成功！");
                session = future.getSession();
                if (session.isConnected()) {
                    session.write("connected");
                }
            } else {
                Log.d(TAG, IP + ":" + PORT + "连接失败！");
                isRunning = false;
            }
            while (isRunning) {
                if (sendQueue.isEmpty()) {
                    SystemClock.sleep(1000);
                } else {
                    if (future.isConnected()) {
                        if (session.isConnected()) {
                            try {
                                String msg = sendQueue.take();
                                //发送消息
                                session.write(msg);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    } else {
                        isRunning = false;
                        break;
                    }
                }
            }
            if (session != null) {
                session.close();
            }
        }
    }

    private class PushBinder extends ISendMsg.Stub {

        @Override
        public void send(String msg) throws RemoteException {
            try {
                if (sendQueue.remainingCapacity() > 0) {
                    sendQueue.put(msg);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory {

        @Override
        public boolean isRequest(IoSession ioSession, Object o) {
            return false;
        }

        @Override
        public boolean isResponse(IoSession ioSession, Object o) {
            if ("2".equals(o)) {
                return true;
            }
            return false;
        }

        @Override
        public Object getRequest(IoSession ioSession) {
            return "1";
        }

        @Override
        public Object getResponse(IoSession ioSession, Object o) {
            return null;
        }
    }
}
